/// Copyright (c) Microsoft Corporation.  All rights reserved.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;
using Microsoft.VSPowerToys.Common.TaskManager;
using Microsoft.VSPowerToys.PackInstallerDataModel;
using System.Threading;
using System.Security.Cryptography;

namespace Microsoft.VSPowerToys.PackInstaller
{
    /// <summary>
    /// This form shows the progress as things are being downloaded and installed by the pack installer.
    /// </summary>
    public partial class ProgressResultsForm : Form
    {
        PackLibrary packData = null;

        private bool performMaintenance = false;
        public event EventHandler<EventArgs> OnToolsInstalled;

        private int numberOfToolsToInstallOrUninstall;
        private int numberOfToolsActuallyInstalledOrUninstalled;

        /// <summary>
        /// Current running instance of task scheduler
        /// </summary>
        private TaskScheduler scheduler;

        /// <summary>
        /// Constructor, requires the Pack and Tool data as input to setup the tasks to be performed and the progress bars.
        /// </summary>
        public ProgressResultsForm(PackLibrary newPackData, bool enableMaintenanceMode)
        {
            InitializeComponent();
            this.performMaintenance = enableMaintenanceMode;
            this.packData = newPackData;
            this.promoPictureBox.ImageLocation = ConfigurableStrings.PromoGraphicsURL;
            totalProgressBar.Value = 0;
            percentCompleteLabel.Text = string.Empty;
            fileSizeLabel.Text = string.Empty;
            this.Font = SystemFonts.DialogFont;
            this.queueCompleteLabel.Font = new Font(SystemFonts.DialogFont, FontStyle.Bold);
        }

        /// <summary>
        /// This method creates the tasks necessary for downloading each of the tools we want to install.
        /// The actual installation will be queued up as a result of a successful download.
        /// </summary>
        public void InstallTools()
        {
            // Use a temp variable for keeping track of the maximum so that 
            // we don't cause the UI to do anything till we set the final value.
            int tempMax = 0;
            this.numberOfToolsToInstallOrUninstall = 0;
            this.numberOfToolsActuallyInstalledOrUninstalled = 0;

            List<ToolItem> toolItemsToInstallWithoutDownload = new List<ToolItem>();

            foreach (ToolItem tool in packData.Tools)
            {
                if (tool.InstallTool)
                {
                    this.numberOfToolsToInstallOrUninstall++;
                    if (!IsSetupFileCorrect(tool))
                    {
                        // Add one to download and one to install...
                        tempMax += 2;
                    }
                    else
                    {
                        // Since we're going to keep a separate list of these tools we're going to
                        // clear the install flag.
                        tool.InstallTool = false;
                        toolItemsToInstallWithoutDownload.Add(tool);
                        // Just add one for the install.
                        tempMax++;
                    }
                }
            }

            totalProgressBar.Maximum = tempMax;

            // Create the task manager to handle downloading and installing the tools.
            scheduler = new TaskScheduler();
            scheduler.TaskCompleted += new EventHandler<TaskCompletedEventArgs>(mgr_TaskCompleted);
            scheduler.QueueCompleted += new EventHandler(mgr_QueueCompleted);
            scheduler.TaskStarting += new EventHandler<TaskEventArgs>(mgr_TaskStarting);
            foreach (ToolItem tool in packData.Tools)
            {
                if (tool.InstallTool)
                {
                    string fileName = Path.Combine(Application.CommonAppDataPath, tool.SetupFileName);
                    DownloadTask task = new DownloadTask(tool.SetupUrl, fileName);
                    task.ProgressAvailable += new EventHandler<TaskProgressEventArgs>(DownloadTaskProgressAvailable);
                    task.Tag = tool;
                    scheduler.EnqueueTask(task);
                }
            }

            foreach (ToolItem installTool in toolItemsToInstallWithoutDownload)
            {
                installTool.InstallTool = true;
                Task installTask = CreateInstallTask(installTool);
                if (installTask != null)
                {
                    installTask.TaskMessageAvailable += new EventHandler<TaskMessageAvailableEventArgs>(this.TaskMessagePosted);
                    scheduler.EnqueueTask(installTask);
                }
            }

            percentCompleteLabel.Text = 0.ToString(Application.CurrentCulture.NumberFormat) + '%';
            scheduler.Start();
        }

        /// <summary>
        /// This method creates the tasks necessary for uninstalling each tool.
        /// </summary>
        public void UninstallTools()
        {
            // Use a temp variable for keeping track of the maximum so that 
            // we don't cause the UI to do anything till we set the final value.
            int tempMax = 0;
            this.numberOfToolsActuallyInstalledOrUninstalled = 0;

            foreach (ToolItem tool in packData.Tools)
            {
                if (tool.InstallTool)
                {
                    tempMax++;
                }
            }
            this.numberOfToolsToInstallOrUninstall = tempMax;

            this.currentDownloadProgressBar.Visible = false;
            this.currentDownloadProgressLabel.Visible = false;
            this.fileSizeLabel.Visible = false;

            totalProgressBar.Maximum = tempMax;

            // Create the task manager to handle uninstalling the tools.
            this.scheduler = new TaskScheduler();
            scheduler.TaskCompleted += new EventHandler<TaskCompletedEventArgs>(uninstallManager_TaskCompleted);
            scheduler.QueueCompleted += new EventHandler(uninstallManager_QueueCompleted);
            scheduler.TaskStarting += new EventHandler<TaskEventArgs>(uninstallManager_TaskStarting);
            foreach (ToolItem tool in packData.Tools)
            {
                if (tool.InstallTool)
                {
                    UninstallSoftwareTask task = new UninstallSoftwareTask(tool.ProductGuid);
                    task.Tag = tool;
                    scheduler.EnqueueTask(task);
                }
            }
            scheduler.Start();
        }

        /// <summary>
        /// This event gets raised when the queue of tasks to be completed is empty.
        /// When all the tasks are done we just want to make sure the Cancel button becomes Close.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void uninstallManager_QueueCompleted(object sender, EventArgs e)
        {
            if (!this.InvokeRequired)
            {
                if (this.totalProgressBar.Value == this.totalProgressBar.Maximum)
                {
                    ((TaskScheduler)sender).Stop(false);
                    this.cancelCloseButton.Text = Strings.ProgressResultsFormCloseButtonText;

                    // Print out how successful the uninstallation was.
                    queueCompleteLabel.Text = this.numberOfToolsActuallyInstalledOrUninstalled.ToString(Application.CurrentCulture.NumberFormat) + Strings.NumberOfToolsSeparatorString + this.numberOfToolsToInstallOrUninstall.ToString(Application.CurrentCulture.NumberFormat) + Strings.NumberOfToolsUninstalledMessage;
                    queueCompleteLabel.Visible = true;
                    this.Text = Strings.UninstallationCompletedTitleText;
                    NativeMethods.FlashTaskbarWindow(this.Owner, 3);

                    this.scheduler = null;
                    // This event is used for testing to help figure out when to check if things went okay.
                    if (this.OnToolsInstalled != null)
                    {
                        this.OnToolsInstalled(this, new EventArgs());
                    }
                }
            }
            else
            {
                if (!this.IsDisposed)
                {
                    this.Invoke(new EventHandler(uninstallManager_QueueCompleted), sender, e);
                }
            }
        }

        /// <summary>
        /// This event gets raised when a task is starting.
        /// We want to print out some information about the start of the task.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void uninstallManager_TaskStarting(object sender, TaskEventArgs e)
        {
            if (!this.InvokeRequired)
            {
                ToolItem currentTool = e.Task.Tag as ToolItem;
                if (currentTool != null)
                {
                    if (e.Task is UninstallSoftwareTask)
                    {
                        this.progressResultsTextBox.AppendText(Strings.ToolUninstallStartStatusMessage + currentTool.ToolName + Strings.ToolStartStatusMessagePostfix + Environment.NewLine);
                    }
                }
            }
            else
            {
                if (!this.IsDisposed)
                    this.Invoke(new EventHandler<TaskEventArgs>(uninstallManager_TaskStarting), sender, new TaskEventArgs(e.Task));
            }
        }

        /// <summary>
        /// This event gets raised when a task is completed.
        /// If the task was a download task then we want to queue up a task for installing that tool.
        /// If the task was an installation task we want to update the error log to include a message about
        /// the success or failure of the installation.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void uninstallManager_TaskCompleted(object sender, TaskCompletedEventArgs e)
        {
            TaskScheduler sendingTaskManager = sender as TaskScheduler;
            if (sendingTaskManager != null)
            {
                if (!this.InvokeRequired)
                {
                    // The task completed so increment the progress bar...
                    UpdatePercentComplete();
                    UninstallSoftwareTask uninstTask = e.OwnerTask as UninstallSoftwareTask;

                    if (uninstTask != null)
                    {
                        ToolItem tool = (ToolItem)(uninstTask.Tag);

                        // Was the uninstall successful?
                        if (e.IsSuccess)
                        {
                            // Print success message
                            this.progressResultsTextBox.AppendText(tool.ToolName + Strings.ToolUninstallSuccessStatusMessage + Environment.NewLine);
                            this.progressResultsTextBox.ScrollToCaret();
                            this.numberOfToolsActuallyInstalledOrUninstalled++;
                        }
                        else
                        {
                            // Print failure message
                            this.progressResultsTextBox.AppendText(Strings.ToolUninstallFailedErrorMessage + tool.ToolName + "." + Environment.NewLine);
                            if (e.ExceptionRaised != null)
                            {
                                this.progressResultsTextBox.AppendText(Strings.ToolFailureReasonText + e.ExceptionRaised.Message + Environment.NewLine);
                            }
                            this.progressResultsTextBox.ScrollToCaret();
                        }
                    }
                }
                else
                {
                    if (!this.IsDisposed)
                        this.Invoke(new EventHandler<TaskCompletedEventArgs>(this.uninstallManager_TaskCompleted), sender, e);
                }
            }
            else
            {
                throw new ArgumentException(PackInstaller.Strings.TaskManagerArgumentExceptionErrorMessage, "sender");
            }
        }

        /// <summary>
        /// This event gets raised when the queue of tasks to be completed is empty.
        /// When all the tasks are done we just want to make sure the Cancel button becomes Close.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void mgr_QueueCompleted(object sender, EventArgs e)
        {
            if (!this.InvokeRequired)
            {
                if (this.totalProgressBar.Value == this.totalProgressBar.Maximum)
                {
                    ((TaskScheduler)sender).Stop(false);
                    this.cancelCloseButton.Text = Strings.ProgressResultsFormCloseButtonText;
                    
                    // Print out how successful the uninstallation was.
                    queueCompleteLabel.Text = this.numberOfToolsActuallyInstalledOrUninstalled.ToString(Application.CurrentCulture.NumberFormat) + Strings.NumberOfToolsSeparatorString + this.numberOfToolsToInstallOrUninstall.ToString(Application.CurrentCulture.NumberFormat) + Strings.NumberOfToolsInstalledMessage;
                    queueCompleteLabel.Visible = true;
                    this.Text = Strings.InstallationCompletedTitleText;
                    NativeMethods.FlashTaskbarWindow(this.Owner, 3);

                    this.scheduler = null;

                    // This event is used for testing to help figure out when to check if things went okay.
                    if (this.OnToolsInstalled != null)
                    {
                        this.OnToolsInstalled(this, new EventArgs());
                    }
                }
            }
            else
            {
                if (!this.IsDisposed)
                    this.Invoke(new EventHandler(mgr_QueueCompleted), sender, e);
            }
        }

        /// <summary>
        /// This event gets raised when a task is starting.
        /// We want to print out some information about the start of the task.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void mgr_TaskStarting(object sender, TaskEventArgs e)
        {
            if (!this.InvokeRequired)
            {
                ToolItem currentTool = e.Task.Tag as ToolItem;
                if (currentTool != null)
                {
                    if (e.Task is DownloadTask)
                    {
                        this.currentDownloadProgressBar.Visible = true;
                        this.currentDownloadProgressLabel.Visible = true;
                        this.fileSizeLabel.Visible = true;
                        this.progressResultsTextBox.AppendText(Strings.ToolDownloadStartStatusMessage + currentTool.ToolName + Strings.ToolStartStatusMessagePostfix + Environment.NewLine);
                    }
                    else if ((e.Task is WindowsInstallerTask) || (e.Task is InstallVsiTask))
                    {
                        this.currentDownloadProgressBar.Visible = false;
                        this.currentDownloadProgressLabel.Visible = false;
                        this.fileSizeLabel.Visible = false;
                        this.progressResultsTextBox.AppendText(Strings.ToolInstallationStartStatusMessage + currentTool.ToolName + Strings.ToolStartStatusMessagePostfix + Environment.NewLine);
                    }
                    this.progressResultsTextBox.ScrollToCaret();
                }

            }
            else
            {
                if (!this.IsDisposed)
                    this.Invoke(new EventHandler<TaskEventArgs>(mgr_TaskStarting), sender, new TaskEventArgs(e.Task));
            }
        }

        /// <summary>
        /// This event gets raised when a task is completed.
        /// If the task was a download task then we want to queue up a task for installing that tool.
        /// If the task was an installation task we want to update the error log to include a message about
        /// the success or failure of the installation.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void mgr_TaskCompleted(object sender, TaskCompletedEventArgs e)
        {
			TaskScheduler sendingTaskManager = sender as TaskScheduler;
			if (sendingTaskManager != null)
			{
				if (!this.InvokeRequired)
				{
                    UpdatePercentComplete();
					DownloadTask dTask = e.OwnerTask as DownloadTask;

                    // Do we have a download task?
                    if (dTask != null)
                    {
                        // In either case below we need to have the tool...
                        ToolItem tool = (ToolItem)(dTask.Tag);

						if (e.IsSuccess)
						{
                            this.progressResultsTextBox.AppendText(tool.ToolName + PackInstaller.Strings.ToolDownloadSuccessStatusMessage + Environment.NewLine);
                            if (IsSetupFileCorrect(tool))
                            {
                                Task installTask = CreateInstallTask(dTask);
                                if (installTask != null)
                                {
                                    installTask.TaskMessageAvailable += new EventHandler<TaskMessageAvailableEventArgs>(this.TaskMessagePosted);
                                    sendingTaskManager.EnqueueTask(installTask);
                                }
                                else
                                {
                                    this.progressResultsTextBox.AppendText(PackInstaller.Strings.ToolDownloadFailedErrorMessage + tool.ToolName + "." + Environment.NewLine);
                                    UpdatePercentComplete();
                                }
                            }
                            else
                            {
                                this.progressResultsTextBox.AppendText(PackInstaller.Strings.DownloadedSetupFileWasNotRight + 
                                    tool.ToolName + PackInstaller.Strings.DownloadedSetupFileWasNotRight2 + Environment.NewLine);

                                this.progressResultsTextBox.AppendText(PackInstaller.Strings.DownloadedSetupFileWasNotRight3 + Environment.NewLine);
                                UpdatePercentComplete();
                            }
                            
						}
						else
						{
							// Print out an error message.
							this.progressResultsTextBox.AppendText(PackInstaller.Strings.ToolDownloadFailedErrorMessage + tool.ToolName + "." + Environment.NewLine);
							if (e.ExceptionRaised != null)
							{
								// If we got an exception we can print out some more info...
								this.progressResultsTextBox.AppendText(PackInstaller.Strings.ToolFailureReasonText + e.ExceptionRaised.Message + Environment.NewLine);
							}

							// Since we won't have an install task to increment this again, increment it now.
                            UpdatePercentComplete();
						}
                        
					}
					// Do we have an install task?
                    else if ((e.OwnerTask is InstallVsiTask) || (e.OwnerTask is WindowsInstallerTask))
					{
						ToolItem tool = (ToolItem)(e.OwnerTask.Tag);
						if (e.IsSuccess)
						{
							// Print out some success text and increment the number of tools we successfully installed...
							this.progressResultsTextBox.AppendText(tool.ToolName + PackInstaller.Strings.ToolInstallationSuccessStatusMessage + Environment.NewLine);
							this.numberOfToolsActuallyInstalledOrUninstalled++;
						}
						else
						{
							// Print out the error text and the exception if we have one.
							this.progressResultsTextBox.AppendText(PackInstaller.Strings.ToolInstallationFailedErrorMessage + tool.ToolName + "." + Environment.NewLine);
							if (e.ExceptionRaised != null)
							{
								this.progressResultsTextBox.AppendText(PackInstaller.Strings.ToolFailureReasonText + e.ExceptionRaised.Message + Environment.NewLine);
							}
						}
					}
                    this.progressResultsTextBox.ScrollToCaret();
				}
				else
				{
                    try
                    {
                        this.Invoke(new EventHandler<TaskCompletedEventArgs>(this.mgr_TaskCompleted), sender, e);
                    }
                    catch (ObjectDisposedException)
                    {
                    }
                }
            }
            else
            {
                throw new ArgumentException(PackInstaller.Strings.TaskManagerArgumentExceptionErrorMessage, "sender");
            }
        }

        /// <summary>
        /// Posts message sent by the task to the log textbox.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void TaskMessagePosted(object sender, TaskMessageAvailableEventArgs e)
        {
            if (!this.InvokeRequired)
            {
                this.progressResultsTextBox.AppendText(e.Message + Environment.NewLine);
                this.progressResultsTextBox.ScrollToCaret();
            }
            else
            {
                try
                {
                    this.Invoke(new EventHandler<TaskMessageAvailableEventArgs>(this.TaskMessagePosted), sender, e);
                }
                catch (ObjectDisposedException)
                {
                }
            }
        }
		/// <summary>
		/// This event updates the status bar as the download tasks fire off.
		/// </summary>
		/// <param name="task"></param>
		/// <param name="current"></param>
		/// <param name="max"></param>
        void DownloadTaskProgressAvailable(object sender, TaskProgressEventArgs e)
        {
            if (!this.InvokeRequired)
            {
                this.currentDownloadProgressBar.Maximum = e.MaximumProgressValue;
                this.currentDownloadProgressBar.Minimum = 0;
                this.currentDownloadProgressBar.Value = e.CurrentProgress;
                this.fileSizeLabel.Text = (e.CurrentProgress / 1024).ToString("N0", Application.CurrentCulture.NumberFormat) +
                    PackInstaller.Strings.DownloadProgressKBLabelText + "/" + (e.MaximumProgressValue / 1024).ToString("N0", Application.CurrentCulture.NumberFormat) +
                    PackInstaller.Strings.DownloadProgressKBLabelText;
            }
            else
            {
                try
                {
                    this.Invoke(new EventHandler<TaskProgressEventArgs>(this.DownloadTaskProgressAvailable), sender, new TaskProgressEventArgs(e.CurrentTask, e.CurrentProgress, e.MaximumProgressValue));
                }
                catch (ObjectDisposedException)
                {
                }
            }
        }

        /// <summary>
        /// This method handles the cancel / close button click.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _CancelCloseButton_Click(object sender, EventArgs e)
        {
            if (scheduler != null)
            {
                this.cancelCloseButton.Enabled = false;
                this.cancelCloseButton.Text = Strings.CloseButtonClosingText;
                this.progressResultsTextBox.AppendText(Strings.TaskCancelledText);
                this.progressResultsTextBox.ScrollToCaret();
                Thread stopThread = new Thread(new ThreadStart(this.CancelAndCloseForm));
                stopThread.Start();
            }
            else
            {
                this.CloseForm();
            }
        }

        /// <summary>
        /// This method cancels the current task and closes the form.
        /// </summary>
        private void CancelAndCloseForm()
        {
            if (scheduler != null)
            {
                scheduler.Stop(true);
            }
            if (this.InvokeRequired)
            {
                this.Invoke(new ThreadStart(this.CloseForm));
            }
            else
            {
                this.CloseForm();
            }
        }

        /// <summary>
        /// This method tells the owner form to refresh its data and closes the current form.
        /// </summary>
        private void CloseForm()
        {
            PackInstallerForm pif = this.Owner as PackInstallerForm;
            if (pif != null)
            {
                pif.RefreshDataAndGui();
                pif.Refresh();
            }
            this.Close();
        }
		/// <summary>
		/// This method fires off the tool installation.  We want to do this here so that the form
		/// can be shown modally and at the same time, not fire off from the constructor.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void ProgressResultsForm_Shown(object sender, EventArgs e)
		{
			if (!this.performMaintenance)
			{
				InstallTools();
			}
			else
			{
				UninstallTools();
			}
        }

        /// <summary>
        /// This method updates the percentage complete indicators.
        /// </summary>
        private void UpdatePercentComplete()
        {
            totalProgressBar.Increment(1);
            totalProgressBar.Refresh();
            percentCompleteLabel.Text = ((int)(((double)totalProgressBar.Value / (double)totalProgressBar.Maximum) * 100.0)).ToString(Application.CurrentCulture.NumberFormat) + '%';
            percentCompleteLabel.Refresh();
            this.Refresh();
        }

        #region Static Members

        /// <summary>
        /// Creates an install task based on the downloaded file extension.
        /// </summary>
        /// <param name="downloadTask"></param>
        private static Task CreateInstallTask(DownloadTask downloadTask)
        {
            if (downloadTask == null)
            {
                throw new ArgumentNullException("downloadTask");
            }
            ToolItem currentTool = downloadTask.Tag as ToolItem;
            Task installTask = null;
            string extension = Path.GetExtension(downloadTask.SaveLocation);
            if (currentTool != null)
            {
                if (extension.Equals(Properties.Resources.ExtensionsMsi, StringComparison.CurrentCultureIgnoreCase)) 
                {
                    // Create the task to install the MSI we just downloaded...
                    installTask = new InstallMsiTask(downloadTask.SaveLocation);
                } 
                else if (extension.Equals(Properties.Resources.ExtensionsVsi, StringComparison.CurrentCultureIgnoreCase)) 
                {
                    installTask = new InstallVsiTask(downloadTask.SaveLocation, true);
                }
                else if (extension.Equals(Properties.Resources.ExtensionsExe, StringComparison.CurrentCultureIgnoreCase))
                {
                    installTask = new InstallExeTask(downloadTask.SaveLocation);
                }

                if (installTask != null)
                {
                    // Associate tool to task
                    installTask.Tag = currentTool;
                }
            }
            return installTask;
        }

        /// <summary>
        /// Creates an install task based on the downloaded file extension.
        /// </summary>
        /// <param name="downloadTask"></param>
        private static Task CreateInstallTask(ToolItem toolToInstall)
        {
            if (toolToInstall == null)
            {
                throw new ArgumentNullException("toolToInstall");
            }

            Task installTask = null;
            string installSourceLocation = Path.Combine(Application.CommonAppDataPath, toolToInstall.SetupFileName);
            string extension = Path.GetExtension(installSourceLocation);
            if (extension.Equals(Properties.Resources.ExtensionsMsi, StringComparison.CurrentCultureIgnoreCase))
            {
                // Create the task to install the MSI we just downloaded...
                installTask = new InstallMsiTask(installSourceLocation);
            }
            else if (extension.Equals(Properties.Resources.ExtensionsVsi, StringComparison.CurrentCultureIgnoreCase))
            {
                installTask = new InstallVsiTask(installSourceLocation, true);
            }
            else if (extension.Equals(Properties.Resources.ExtensionsExe, StringComparison.CurrentCultureIgnoreCase))
            {
                installTask = new InstallExeTask(installSourceLocation);
            }

            if (installTask != null)
            {
                // Associate tool to task
                installTask.Tag = toolToInstall;
            }
            return installTask;
        }

        /// <summary>
        /// Returns whether the setup file that we need to download already exists on the local machine.
        /// </summary>
        /// <param name="tool"></param>
        private static bool IsSetupFileCorrect(ToolItem tool)
        {
            bool fileIsCorrect = false;

            string fileName = Path.Combine(Application.CommonAppDataPath, tool.SetupFileName);
            if (File.Exists(fileName))
            {
                MD5CryptoServiceProvider cryptoProvider = new MD5CryptoServiceProvider();
                
                FileStream inputFileStream = File.OpenRead(fileName);
                byte[] fileHash = cryptoProvider.ComputeHash(inputFileStream);
                inputFileStream.Close();
                string stringHash = System.BitConverter.ToString(fileHash);

                if (string.Equals(tool.SetupFileHash, stringHash))
                {
                    fileIsCorrect = true;
                }
            }

            return (fileIsCorrect);
        }

        #endregion 
    }
}
